package com.wu.sudoku;

import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;

public class Game extends Activity {

	private static final String TAG = "game";

	public static final String KEY_DIFFICULTY = "sudoku.difficluty";

	public static final int DIFFICULTY_EASY = 0;
	public static final int DIFFICULTY_MEDIUM = 1;
	public static final int DIFFICULTY_HARD = 2;

	private static final String PREF_PUZZLE = "puzzle";
	protected static final int DIFFICULTY_CONTINUE = -1;

	private int puzzle[] = new int[9 * 9];

	private PuzzleView puzzleView;

	private int[][][] used = new int[9][9][];

	private final String easyPuzzle = "360000000004230800000004200"
			+ "070460003820000014500013020" + "001900000007048300000000045";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(TAG, "onCreate");

		int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
		puzzle = getPuzzle(diff);
		calculateUsedTiles();

		puzzleView = new PuzzleView(this);
		setContentView(puzzleView);
		puzzleView.requestFocus();
		// if the activity is restarted , do a continue next time
		getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
	}

	@Override
	protected void onPause() {
		super.onPause();
		Log.d(TAG, "onPause");
		// Music
		// save the current puzzle
		getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE,
				toPuzzleString(puzzle)).commit();
	}

	private int[] getPuzzle(int diff) {
		String puz;
		// TODO continue last game
		switch (diff) {
		case DIFFICULTY_EASY:
			puz = easyPuzzle;
			puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE,
					easyPuzzle);
			break;
		case DIFFICULTY_MEDIUM:
			puz = easyPuzzle;

			break;
		case DIFFICULTY_HARD:
			puz = easyPuzzle;

			break;

		case DIFFICULTY_CONTINUE:
			puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE,
					easyPuzzle);

			break;
		default:
			puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE,
					easyPuzzle);
			break;
		}
		return fromPuzzleString(puz);
	}

	private int[] fromPuzzleString(String puz) {
		int puzzle[] = new int[puz.length()];
		for (int i = 0; i < puzzle.length; i++) {
			puzzle[i] = puz.charAt(i) - '0';
		}
		return puzzle;
	}

	private void calculateUsedTiles() {
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				used[i][j] = calculateUsedTiles(i, j);
			}
		}
	}

	private int[] calculateUsedTiles(int x, int y) {
		int c[] = new int[9];
		// horizontal
		for (int i = 0; i < 9; i++) {
			if (i == y)
				continue;
			int t = getTile(x, i);
			if (t != 0) {
				c[t - 1] = t;
			}
		}
		// vertical
		for (int i = 0; i < 9; i++) {
			if (i == x)
				continue;
			int t = getTile(i, y);
			if (t != 0) {
				c[t - 1] = t;
			}
		}
		// same cell block
		int startX = (x / 3) * 3;
		int startY = (y / 3) * 3;
		for (int i = startX; i < startX + 3; i++) {
			for (int j = startY; j < startY + 3; j++) {
				if (i == x && j == y) {
					continue;
				}
				int t = getTile(i, j);
				if (t != 0) {
					c[t - 1] = t;
				}
			}
		}
		// compress
		int nused = 0;
		for (int i : c) {
			if (i != 0) {
				nused++;
			}
		}
		int result[] = new int[nused];
		nused = 0;
		for (int i : c) {
			if (i != 0) {
				result[nused++] = i;
			}
		}
		return result;
	}

	public int getTile(int x, int y) {
		return puzzle[y * 9 + x];
	}

	private void setTile(int x, int y, int value) {
		puzzle[y * 9 + x] = value;
	}

	public void showKeypadOrError(int x, int y) {
		int tiles[] = getUsedTile(x, y);
		if (tiles.length == 9) {
			Toast toast = Toast.makeText(this, R.string.no_moves_label,
					Toast.LENGTH_SHORT);
			toast.setGravity(Gravity.CENTER, 0, 0);
			toast.show();
		} else {
			Log.d(TAG, "showKeypad:used=" + toPuzzleString(tiles));
			Dialog keypad = new Keypad(this, tiles, puzzleView);
			keypad.show();
		}
	}

	private String toPuzzleString(int[] tiles) {
		StringBuffer strPuzzle = new StringBuffer();
		for (int i = 0; i < tiles.length; i++) {
			strPuzzle.append(tiles[i]);
		}
		return strPuzzle.toString();
	}

	public int[] getUsedTile(int x, int y) {
		return used[x][y];
	}

	public boolean setTileIfValid(int selX, int selY, int tile) {
		int tiles[] = getUsedTile(selX, selY);
		if (tile != 0) {
			for (int i = 0; i < tiles.length; i++) {
				if (tiles[i] == tile) {
					return false;
				}
			}
		}
		setTile(selX, selY, tile);
		calculateUsedTiles();
		return true;
	}
}
